﻿using System;

using System.Collections.Generic;
using System.Text;
using Silvermoon.Navigation;
using Silvermoon.UI;
using Silvermoon.Windows;
using System.Threading;
using Silvermoon.Classes;

namespace Silvermoon.Controls
{
    /// <summary>
    /// Specialized Window class to support navigation.
    /// </summary>
    public class Page : Window
    {
        #region fields

        private NavigationService navigationService;

        #endregion
        #region props

        public static readonly Command BackCommand = new Command();
        public static readonly Command HomeCommand = new Command();

        /// <summary>
        /// Gets the <see cref="PageNavigator"/> to navigate through pages.
        /// </summary>
        public NavigationService NavigationService
        {
            get
            {
                if (navigationService == null) navigationService = new NavigationService();
                return navigationService;
            }
            set
            {

                navigationService = value;
            }
        }

        /// <summary>
        /// Specifies whether the page is not disposed after navigating away.
        /// </summary>
        public bool KeepAlive { get; set; }

        #endregion
        #region ctor/dtor
        protected override void Dispose(bool dispose)
        {
            NavigationService = null;
            base.Dispose(dispose);
        }
        #endregion
        #region methods

        /// <summary>
        /// Navigates back to the previous page.
        /// </summary>
        protected override void OnBack(HandledEventArgs e)
        {
            base.OnBack(e);
            if (!e.Handled)
            {
                if (navigationService != null) NavigationService.GoBack();
            }
        }

        /// <summary>
        /// Navigates to the home page.
        /// </summary>
        protected override void OnHome(HandledEventArgs e)
        {
            base.OnHome(e);
            if (!e.Handled)
            {
                if (navigationService != null) NavigationService.GoHome();
            }
        }

        public void RemoveFromStack()
        {
            if (navigationService != null)  navigationService.RemoveFromStack(this);
        }

        protected override void OnHiding()
        {
            ExitAllThreads();
            base.OnHiding();
        }

        protected override void OnShown()
        {
            base.OnShown();
            if (navigationService != null) NavigationService.OnPageShown(this);
        }

        protected override void OnHidden()
        {
            base.OnHidden();
            if (navigationService != null) NavigationService.OnPageHidden(this);
            ExitAllThreads();
        }

        /// <summary>
        /// Closes the page without transition.
        /// </summary>
        public virtual void Close()
        {
            if (!IsHidden)
            {
                OnHiding();
                //if (TransitionManager != null) TransitionManager.GoTo(this, VState.Hidden, false); else Visibility = 0f;
                Visibility = 0f;
            }
        }

        /// <summary>
        /// Opens the page without transition.
        /// </summary>
        public virtual void Open()
        {
            Open(false);
        }

        public void Open(bool atBack)
        {
            if (!IsShown)
            {
                if (atBack)
                {
                    Screen.Attach(this);
                    Screen.SendToBack(this);
                }
                OnShowing();
                //if (TransitionManager != null) TransitionManager.GoTo(this, VState.Shown, false); else Visibility = 1f;
                Visibility = 1f;
            }
        }


        /// <summary>
        /// Navigates forward to another page
        /// </summary>
        /// <param name="page">Page to navigate to.</param>
        public void NavigateTo(Page page)
        {
            if (page == null) throw new ArgumentNullException("page");
            NavigationService.NavigateTo(page);
        }

        /// <summary>
        /// Navigates several pages back.
        /// </summary>
        /// <param name="level">Number of pages to go back.</param>
        public void NavigateBack(int level)
        {
            NavigationService.GoBack(level);
        }

        /// <summary>
        /// Returns an object that contains data about the current view state.
        /// See also <seealso cref="OnLoadViewState"/>.
        /// </summary>
        /// <returns>Object containing the current view state, otherwis null.</returns>
        public virtual object OnSaveViewState()
        {
            if (SaveViewState != null)
            {
                ViewStateEventArgs args = new ViewStateEventArgs();
                SaveViewState(this, args);
                return args.ViewState;
            }
            return null;
        }

        /// <summary>
        /// Initializes the page with information from the specified view state.
        /// See also <seealso cref="OnSaveViewState"/>.
        /// </summary>
        /// <param name="viewState">View state, which was previously generated with <see cref="SaveViewState"/>.</param>
        public virtual void OnLoadViewState(object viewState)
        {
            if (LoadViewState != null)
            {
                ViewStateEventArgs args = new ViewStateEventArgs { ViewState = viewState };
                LoadViewState(this, args);
            }
        }

        /// <summary>
        /// Occurs when another page navigates to this page.
        /// </summary>
        /// <param name="from">Page from where to navigate from.</param>
        public virtual void OnNavigateFrom(Page from)
        {
        }

        public virtual void OnNavigateTo(Page to)
        {
        }


        protected internal override void OnCommand(CommandEventArgs args)
        {
            if (args.Command == BackCommand)
            {
                args.Cancel = true;
                args.Handled = true;
                GoBack();
            }
            else if (args.Command == HomeCommand)
            {
                args.Cancel = true;
                args.Handled = true;
                GoHome();
            }

            base.OnCommand(args);
        }

        /// <summary>
        /// Occurs when the exit application "OK" button of the phone is pressed.
        /// By default, if the page is the root page, a dialog appears to let the user choose to exit the application, 
        /// otherwise it causes a GoBack method call.
        /// </summary>
        public override void OnExitApplication()
        {
            if (navigationService != null && !navigationService.IsRoot) GoBack();
            else base.OnExitApplication();
        }

        #endregion
        #region events

        /// <summary>
        /// Loads the view state of the page.
        /// See also <seealso cref="SaveViewState"/>.
        /// </summary>
        public event EventHandler<ViewStateEventArgs> LoadViewState;

        /// <summary>
        /// Saves the view state of the page.
        /// See also <seealso cref="LoadViewState"/>.
        /// </summary>
        public event EventHandler<ViewStateEventArgs> SaveViewState;

        #endregion

    }
}
